home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 May: Tool Chest / Developer CD Series Tool Chest (Apple Computer)(May 1999).iso / Tool Chest / Networking / MacTCP / MacTCP Developer Tools / 802 LAP / LAP802.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  17.7 KB  |  641 lines  |  [TEXT/MPS ]

  1. /* LAP802.c  contains the IEEE 802.3 LAP interface code for IP
  2.  
  3.    (c) Copyright 1990-91 by Apple Computer, Inc.  All rights reserved.
  4.  
  5. */
  6.  
  7. /*
  8.     1.2        Oct 1990    Rajesh    modified for IEEE 802.3 LAP.
  9.     1.0d2    11/25/87    JEM    Changes for CITI-like interface
  10.     1.0d1    9/14/87     JEM    Initial rewrite for "attachPH" interface to Enet driver
  11. */
  12.  
  13. #define __ALLNU__                            /* allow MAC II ROM functions */
  14.  
  15. #include <Devices.h>
  16. #include <Errors.h>
  17. #include <Events.h>
  18. #include <Memory.h>
  19. #include <Traps.h>
  20. #include <Retrace.h>
  21. #include <Resources.h>
  22. #include <ROMDefs.h> 
  23. #include <Slots.h>
  24. #include <AppleTalk.h>
  25.  
  26. #include "MacTCPCommonTypes.h"
  27. #include "MiscIPPB.h"
  28. #include "LAPMisc.h"
  29. #include "LAP802.h"
  30.  
  31. #define    SlotManage    0xA06E                    /* slot manager trap */
  32. #define    UnimplTrap    0xA89F                    /* unimplemented trap trap */
  33.  
  34. #define    spCategoryMask    0x08                /* mask off catagory field */
  35. #define spCTypeMask        0x04                /* mask off type field */
  36. #define    spDrvrSWMask    0x02                /* mask off driver software field */
  37. #define spDrvrHWMask    0x01                /* mask off driver hardware field */
  38.  
  39. /* definitions of LAP handler routines */
  40. extern OSErr Lap802_init(struct Lap802Info *lap);
  41. extern OSErr Lap802_open(struct Lap802Info *lap);
  42. extern OSErr Lap802_attachPH(struct Lap802Info *lap, ProcPtr ptr);
  43. extern OSErr Lap802_detachPH(struct Lap802Info *lap);
  44. extern void Lap802_read_ph();
  45. extern void Lap802p3_ph();
  46. extern void Lap802_readE_ph();
  47. extern OSErr Lap802_write(struct Lap802Info *lap, ip_addr dest, struct ipbuf *ipb);
  48. extern OSErr Lap802_control(struct Lap802Info *lap);
  49. extern void Lap802_fault(struct Lap802Info *lap);
  50. extern OSErr Lap802_statistics(tempLap, statsPtr);
  51. extern Boolean Lap802_register(struct Lap802Info *lap);
  52. extern Boolean Lap802_probe(struct Lap802Info *lap, ip_addr addr);
  53. extern OSErr Lap802_close(struct Lap802Info *lap);
  54.  
  55. extern void TLoopBack(struct wdsEntry *wds);
  56. extern long L802Attach(ProcPtr prot_handler, long ioRefNum, char *protType);
  57. extern long L802Detach(long ioRefNum, char *protType);
  58. extern Ptr A5Swap(Ptr oldA5);
  59. extern void bzero(char *ptr, int len);
  60. extern void IOComplete(struct ipbuf *ipb);
  61. extern Ptr GetA0(void);
  62. extern Ptr GetA5(void);
  63.  
  64.  
  65. /* other IEEE 802.3 internal routines */
  66. void Lap802_writecomplete(void);
  67. void config_RARP(struct Lap802Info *lap);
  68. void SendRARP (struct Lap802Info *lap, int arp_code);
  69.  
  70. struct Lap802Info *Lap802_main()
  71. {
  72.     struct Lap802Info *lap;
  73.  
  74.     lap = (struct Lap802Info *) NewPtr(sizeof(struct Lap802Info));
  75.     if (lap != nil) {
  76.         bzero((Ptr)lap, sizeof(struct Lap802Info));
  77.  
  78.         lap->lapInit = Lap802_init;
  79.         lap->lapOpen = Lap802_open;
  80.         lap->lapClose = Lap802_close;
  81.         lap->lapUnload = nil;
  82.         lap->lapAttach = Lap802_attachPH;
  83.         lap->lapDetach = Lap802_detachPH;
  84.         lap->lapOutput = Lap802_write;
  85.         lap->lapControl = Lap802_control;
  86.         lap->lapFault = del_arp_entry;
  87.         lap->lapRegister = Lap802_register;
  88.         lap->lapProbe = Lap802_probe;
  89.         lap->lapConfigure = config_RARP;
  90.         lap->lapStatistics = Lap802_statistics;
  91.         lap->lapFindGateway = nil;
  92.         lap->lapGwyCheck = nil;
  93.         lap->headerSize = sizeof(struct Lap802_header);
  94.         lap->outMaxPacketSize = MAX_LAP802_PKT;
  95.         lap->inMaxPacketSize = MAX_LAP802_PKT;
  96.         lap->maxDataSize = MAX_LAP802_PKT - sizeof(struct Lap802_header);
  97.         
  98.         lap->lapType = ARP_ETHERNET;
  99.         lap->lapAddrLength = sizeof(struct Lap802_addr);
  100.         lap->lapAddrPtr = (Ptr) &lap->our_lap_addr;
  101.         
  102.         lap->lap_broadcast_addr.lap_hi= 0xFFFF;
  103.         lap->lap_broadcast_addr.lap_lo = 0xFFFFFFFF;
  104.         
  105.         lap->ipGlobals = GetA5();
  106.         lap->addressConflict = false;
  107.  
  108.         SetLAPPtr(lap);
  109.     }
  110.     return(lap);
  111. }    
  112.  
  113.  
  114. OSErr Lap802_init(lap, disconnectProc)
  115. struct Lap802Info *lap;
  116. ProcPtr disconnectProc;
  117. {
  118.     OSErr    rc = -1;
  119.     struct Lap802PB     lappb;
  120.     struct SpBlock    sb;
  121.     struct SlotDevParam xpb;
  122.     char driver_name[8];
  123.     char prot_IP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_0,HEX_0};
  124.     char prot_ARP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_6,HEX_0};
  125.     
  126.     lap->ip_ph = nil;
  127.  
  128.     /* open .ENET driver */
  129.     driver_name[0] = '\005';
  130.     driver_name[1] = '.';
  131.     driver_name[2] = 'E';
  132.     driver_name[3] = 'N';
  133.     driver_name[4] = 'E';
  134.     driver_name[5] = 'T';
  135.  
  136.     bzero((char *)&xpb, sizeof(xpb));
  137.     xpb.ioNamePtr = (StringPtr)&driver_name[0];
  138.  
  139.     if (NGetTrapAddress(SlotManage,OSTrap) != 
  140.         NGetTrapAddress(UnimplTrap,OSTrap)) { 
  141.         /* running on a system with a slot manager (Mac II)
  142.            determine which slot Ethernet card is in */
  143.  
  144.         /* search through Nu-bus for the first networking card */
  145.         bzero((char *)&sb, sizeof(sb));
  146.         sb.spSlot = lap->lc.slot;
  147.         sb.spCategory = catNetwork;
  148.         sb.spCType = typeEtherNet;
  149.         sb.spTBMask = spDrvrSWMask | spDrvrHWMask;
  150.         rc = SNextTypeSRsrc(&sb);
  151.  
  152.         if ((lap->lc.slot != 0) && (sb.spSlot != lap->lc.slot)) {
  153.             /* slot of network card as set by Control Panel, isn't valid */
  154.             rc = smEmptySlot;
  155.         }
  156.  
  157.         if (rc == noErr) {
  158.             xpb.ioSlot = sb.spSlot;
  159.             xpb.ioID = sb.spID;
  160. // Debugger();    /* RAJESH MAY 22, 1991 */
  161.             rc = OpenSlot((ParmBlkPtr)&xpb, false);
  162.             lap->link_unit = xpb.ioRefNum;
  163.         }
  164.     };
  165.     if (rc != noErr)  {
  166.         /* running on older system, just try opening driver */
  167.         driver_name[0] = '\006';
  168.         driver_name[6] = '0';
  169.         rc = PBOpen((ParmBlkPtr)&xpb, false);
  170.         lap->link_unit = xpb.ioRefNum;
  171.     };
  172.  
  173.     if (rc == noErr) {
  174.         /* get our Ethernet address from board */
  175.         bzero((char *)&lappb, sizeof(lappb));
  176.         lappb.ioRefNum = lap->link_unit;
  177.         lappb.csCode = TGetInfo;
  178.         lappb.csParam.TGetInfoPB.bufSize = sizeof(lap->our_lap_addr);
  179.         lappb.csParam.TGetInfoPB.infoPtr = (char *)&lap->our_lap_addr;
  180.         rc = PBControl((ParmBlkPtr)&lappb, false);
  181.     }
  182.  
  183.     if (rc == noErr) {
  184.         /* set general mode for large IP IEEE 802.3 packets */
  185.         lappb.csCode = TSetGeneral;
  186.         rc = PBControl((ParmBlkPtr)&lappb, false);
  187.     }
  188.  
  189.     if (rc == noErr) {
  190.             /* attach ethernet-IP protocol read handler to the ethernet driver */
  191.         lappb.csCode = TAttachPH;
  192.         lappb.csParam.TAttachPB.protocolType = LAP_IP;
  193.         lappb.csParam.TAttachPB.PHaddress = (ProcPtr) Lap802_readE_ph;
  194.         rc = PBControl((ParmBlkPtr)&lappb, false);
  195.     }
  196.  
  197.     if (rc == noErr) {    /* attach 802.3-IP packet read handler to LAP manager */
  198.         rc = L802Attach((ProcPtr) Lap802p3_ph, (long) lap->link_unit, prot_IP);
  199.     }
  200.  
  201.     if (rc == noErr) {
  202.             /* attach ethernet-ARP protocol read handler to the ethernet driver */
  203.         lappb.csCode = TAttachPH;
  204.         lappb.csParam.TAttachPB.protocolType = LAP_ARP;
  205.         lappb.csParam.TAttachPB.PHaddress = (ProcPtr) Lap802_readE_ph;
  206.         rc = PBControl((ParmBlkPtr)&lappb, false);
  207.     }
  208.  
  209.     if (rc == noErr) {    /* attach 802.3-ARP packet read handler to LAP manager */
  210.         rc = L802Attach((ProcPtr) Lap802p3_ph, (long) lap->link_unit, prot_ARP);
  211.     }
  212.  
  213.     if (rc == noErr) {    
  214.         /* finally, IEEE 802.3 needs the services of ARP. So start it now. */
  215.         rc = Arp_init(lap);
  216.     }
  217.     return(rc);
  218. }
  219.  
  220.  
  221. OSErr Lap802_open(lap)
  222. struct Lap802Info *lap;
  223. {
  224. #pragma unused (lap)
  225.     return(noErr);
  226. }
  227.  
  228.  
  229. /* Lap802_attachPH is called by IP to specify the address of the IP packet
  230.    received routine */
  231.  
  232. OSErr Lap802_attachPH(lap, ptr)
  233. struct Lap802Info *lap;
  234. voidProcPtr ptr;
  235. {
  236.     lap->ip_ph = ptr;
  237.     return(noErr);
  238. }
  239.  
  240.  
  241. /* Lap802_detachPH is called by IP to release its packet receive routine */
  242.  
  243. OSErr Lap802_detachPH(lap)
  244. struct Lap802Info *lap;
  245. {
  246.     lap->ip_ph = nil;
  247.     return(noErr);
  248. }
  249.  
  250. /* Lap802_read_ph is called by the Ethernet driver when a packet is received */
  251.  
  252. void Lap802_read_ph()        /* reads IEEE 802.3 packets */
  253. {
  254.     struct rdStruct rds;
  255.     struct Lap802_header    *lap_hdr;
  256.     struct Lap802Info *lap;
  257.     Ptr oldA5;
  258.  
  259.     /* save various values required by ReadPacket/ReadRest */    
  260.     lap_hdr = (struct Lap802_header *) SetUpRDS(&rds);
  261.     lap_hdr--;
  262.     lap = (struct Lap802Info *)GetLAPPtr();
  263.     oldA5 = (Ptr) A5Swap(lap->ipGlobals);
  264.  
  265.     rds.lap = (struct LAPInfo *)lap;
  266.       rds.laphdr.length = sizeof(struct Lap802_header);
  267.       rds.laphdr.ptr = (Ptr) lap_hdr;
  268.  
  269.     rds.lapBroadcast = (lap_hdr->lap_dest.lap_hi == 0xffff) && (lap_hdr->lap_dest.lap_lo == 0xffffffffL);
  270.  
  271.       /* process packet */
  272.     if ((lap_hdr->lap_ls.lap_type == LAP_IP) && (lap->ip_ph != nil)) {
  273.            /* give to IP packet receiver */
  274.            lap->Lap802_stats.ip.pktin++;
  275.            (*lap->ip_ph)(&rds);
  276.     }
  277.     else if (lap_hdr->lap_ls.lap_type == LAP_ARP) {
  278.         /* give ARP packet to arp process */
  279.         lap->Lap802_stats.arp.pktin++;
  280.         Arp_read_ph(&rds);
  281.     }
  282.     else if (lap_hdr->lap_ls.lap_type == LAP_RARP) {
  283.         /* give RARP packet to arp process */
  284.         RARP_read_ph(&rds);
  285.     }
  286.     else {
  287.         /* quietly discard unknown IEEE 802.3 packet types */
  288.         lap->Lap802_stats.unknown++;
  289.         ReadRest(&rds, nil, 0);
  290.     }
  291.     (void) A5Swap(oldA5);
  292. }
  293.  
  294. /* Lap802_readE_ph is called by the Ethernet driver when a packet is received */
  295.  
  296. void Lap802_readE_ph()        /* read Ethernet packets */
  297. {
  298.     struct rdStruct rds;
  299.     struct Enet_header    *en_hdr;
  300.     struct Lap802Info *lap;
  301.     Ptr oldA5;
  302.  
  303.     /* save various values required by ReadPacket/ReadRest */    
  304.     en_hdr = (struct Enet_header *) SetUpRDS(&rds);
  305.     en_hdr--;
  306.     lap = (struct Lap802Info *)GetLAPPtr();
  307.     oldA5 = (Ptr) A5Swap(lap->ipGlobals);
  308.  
  309.     rds.lap = (struct LAPInfo *)lap;
  310.       rds.laphdr.length = sizeof(struct Enet_header);
  311.       rds.laphdr.ptr = (Ptr) en_hdr;
  312.  
  313.     rds.lapBroadcast = (en_hdr->en_dest.en_hi == 0xffff) && (en_hdr->en_dest.en_lo == 0xffffffffL);
  314.  
  315.       /* process packet */
  316.     if ((en_hdr->en_type == LAP_IP) && (lap->ip_ph != nil)) {
  317.            /* give to IP packet receiver */
  318.            lap->Lap802_stats.ip.pktin++;
  319.            (*lap->ip_ph)(&rds);
  320.     }
  321.     else if (en_hdr->en_type == LAP_ARP) {
  322.         /* give ARP packet to arp process */
  323.         lap->Lap802_stats.arp.pktin++;
  324.         Arp_read_ph(&rds);
  325.     }
  326.     else if (en_hdr->en_type == LAP_RARP) {
  327.         /* give RARP packet to arp process */
  328.         RARP_read_ph(&rds);
  329.     }
  330.     else {
  331.         /* quietly discard unknown Ethernet packet types */
  332.         lap->Lap802_stats.unknown++;
  333.         ReadRest(&rds, nil, 0);
  334.     }
  335.     (void) A5Swap(oldA5);
  336. }
  337.  
  338. /* Lap802_writecomplete is called when IEEE 802.3 output is complete.  It picks up A0
  339.    (pointer to the ipb), sets up the global information (for IP) and then calls the 
  340.    higher-level ioc routine. */
  341.  
  342. void Lap802_writecomplete()
  343. {
  344.     struct ipbuf *ipb;
  345.     Ptr oldA5;
  346.  
  347.     ipb = (struct ipbuf *) GetA0();
  348.     oldA5 = (Ptr) A5Swap(((struct Lap802Info *)GetLAPPtr())->ipGlobals);
  349.     ipb->iop.ioCompletion = ipb->ip_ioc;
  350. /*    ipb->iop.ioNamePtr = (StringPtr) ipb->callerA5;*/
  351.     IOComplete(ipb);
  352.     (void) A5Swap(oldA5);
  353. }
  354.  
  355. /* Lap802_write is called to initiate a transmission of the indicated
  356.    IEEE 802.3 packet after translating the IP address to IEEE 802.3 address. 
  357.    This is the normal entry point for sending packets. */
  358.  
  359. OSErr Lap802_write(lap, dest, ipb)
  360. struct Lap802Info *lap;
  361. ip_addr dest;
  362. struct ipbuf *ipb;
  363. {
  364.     struct Lap802_header *lap_hdr;
  365.     struct arp_info *arp;
  366.     struct Lap802_addr *tka;
  367.     struct ipbuf *arpipb, *next_ipb;    
  368.     short oldPS;
  369.     OSErr rc;
  370.  
  371.     lap_hdr = (struct Lap802_header *)ipb->laphdr.ptr;
  372.     if ((lap_hdr == nil) || (ipb->laphdr.length < sizeof(struct Lap802_header))) {
  373.         /* WDS for the LAP wasn't set-up correctly */
  374.         return(ipBadWDSErr);
  375.     }
  376.  
  377.     ipb->laphdr.length = sizeof (struct Lap802_header);
  378.  
  379.     /* mark I/O as in progress */
  380.     ipb->iop.ioResult = inProgress;
  381.  
  382.     /* save away caller's IOC address */
  383.     ipb->ip_ioc = ipb->iop.ioCompletion;
  384. /*    ipb->callerA5 = ipb->iop.ioNamePtr;*/
  385.     ipb->iop.ioCompletion = (ProcPtr) Lap802_writecomplete;
  386.  
  387.     lap_hdr->lap_len = 0;        /* calculate packet length in Lap802_writeit procedure */
  388.     lap_hdr->lap_ls.lap_dsap = HEX_AA;
  389.     lap_hdr->lap_ls.lap_ssap = HEX_AA;
  390.     lap_hdr->lap_ls.lap_cntl = HEX_3;
  391.     lap_hdr->lap_ls.lap_orghi = 0;
  392.     lap_hdr->lap_ls.lap_orglo = 0;
  393.     lap_hdr->lap_ls.lap_type = LAP_IP;
  394.  
  395.     oldPS = Disable();
  396.     /* source address set by Ethernet driver. find destination address from ARP table */
  397.     if (dest == lap->our_ip_addr || dest == lap->ip_broadcast_addr) {
  398.         /* trying to send to ourselves.  Since Ethernet is half-duplex,
  399.            simulate the loopback */
  400.         tka = &lap->our_lap_addr;
  401.         lap_hdr->lap_dest = *tka;
  402.         TLoopBack(&ipb->laphdr);
  403.         if (dest == lap->ip_broadcast_addr) tka = IP_to_Lap802(lap, dest);
  404.     }
  405.     else
  406.         tka = IP_to_Lap802(lap, dest);
  407.  
  408.     if (tka) {
  409.         /* copy destination IEEE 802.3 address into packet and send */
  410.         lap_hdr->lap_dest = *tka;
  411.         rc = Lap802_writeit(lap, ipb);
  412.     }
  413.     else {
  414.         /* IEEE 802.3 address not available, send an ARP. Overlay ARP control
  415.            info on top of LAP header area */
  416.         arpipb = (struct ipbuf *)lap->arp_q.qHead;
  417.         while (arpipb) {
  418.             next_ipb = (struct ipbuf *)arpipb->iop.qLink;
  419.             if (((struct arp_info *)(arpipb->laphdr.ptr))->addr == dest) {
  420.                 /* just enque it and don't send out another ARP yet */
  421.                 arp = (struct arp_info *)ipb->laphdr.ptr;
  422.                 arp->timer = 3;
  423.                 arp->rtx = 0;
  424.                 arp->addr = dest;
  425.                 ipb->iop.qLink = 0;
  426.                 Enqueue((QElemPtr)ipb, &lap->arp_q);
  427.                 break;
  428.                 }
  429.             /* look at next packet in queue */
  430.             arpipb = (struct ipbuf *)next_ipb;
  431.         }
  432.         if (arpipb == nil) {
  433.             arp = (struct arp_info *)ipb->laphdr.ptr;
  434.             arp->timer = 3;
  435.             arp->rtx = 0;
  436.             arp->addr = dest;
  437.             SendARP(lap, ARP_REQUEST, dest, &lap->lap_broadcast_addr);
  438.             ipb->iop.qLink = 0;
  439.             Enqueue((QElemPtr)ipb, &lap->arp_q);
  440.         }
  441.         rc = noErr;
  442.     }
  443.     Enable(oldPS);
  444.     return(rc);
  445. }
  446.  
  447. /* Lap802_Writeit is called to set up the IEEE 802.3 header and issue a write to the
  448.    driver.  Caller must have filled in the wds and ioCompletion address, if any. */
  449.  
  450. OSErr Lap802_writeit(lap, ipb)
  451. struct Lap802Info *lap;
  452. struct ipbuf *ipb;
  453. {
  454.     struct Lap802PB *tpb;
  455.     struct wds *wdsp;
  456.     struct Lap802_header *lap_hdr;
  457.     struct wdsEntry *wds;
  458.     unsigned short packetLen=0;
  459.  
  460.     lap_hdr = (struct Lap802_header *)ipb->laphdr.ptr;
  461.     wds = (struct wdsEntry *) &ipb->ip;
  462.     if (wds->length)    packetLen += wds->length;
  463.     wds = (struct wdsEntry *) &ipb->tp;
  464.     if (wds->length)    packetLen += wds->length;
  465.     wds = (struct wdsEntry *) &ipb->data;
  466.     if (wds->length)    packetLen += wds->length;
  467.     lap_hdr->lap_len = packetLen + sizeof(struct LLC_SNAP_header);
  468.  
  469.     tpb = (struct Lap802PB *)ipb;
  470.     tpb->ioVRefNum = 0;
  471.     tpb->ioRefNum = lap->link_unit;
  472.     tpb->csCode = TWrite;
  473.     wdsp = (struct wds *)&(ipb->laphdr.length);
  474.     tpb->csParam.TWritePB.wdsPtr = wdsp;
  475.     return(PBControl((ParmBlkPtr)tpb, true));
  476. }
  477.  
  478. OSErr Lap802_control(lap)
  479. struct Lap802Info *lap;
  480. {
  481. #pragma unused (lap)
  482.     return(unimpErr);
  483. }
  484.  
  485. OSErr Lap802_statistics(tempLap, statsPtr)
  486. struct LAPInfo *tempLap;
  487. struct LAPStats *statsPtr;
  488. {
  489. struct Lap802Info *lap;
  490. #ifdef MPW3.0
  491. #pragma unused (lap)
  492. #endif
  493.     lap = (struct Lap802Info *)tempLap;
  494.     statsPtr->ifType = 1;
  495.     statsPtr->ifMaxMTU = MAX_LAP802_PKT;
  496.     statsPtr->ifSpeed = LAP802SPEED;
  497.     statsPtr->ifPhyAddrLength = sizeof(struct Lap802_addr);
  498.     statsPtr->ifPhysicalAddress = (char *)&lap->our_lap_addr;
  499.     statsPtr->AddrXlation.arp_table = &lap->arp_table[0];
  500.     return(noErr);
  501. }
  502.  
  503. void config_RARP(lap)
  504. struct Lap802Info *lap;
  505. {
  506.     int rtxCount;
  507.     int rtxTime, rtxInterval;
  508.     struct Lap802PB lappb;
  509.     OSErr rc=-1;
  510.     char prot_RARP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_80,HEX_35,HEX_0};
  511.  
  512.         /* attach ethernet-RARP packet read handler to the ethernet driver */
  513.     bzero((char *)&lappb, sizeof(lappb));
  514.     lappb.ioRefNum = lap->link_unit;
  515.     lappb.csCode = TAttachPH;
  516.     lappb.csParam.TAttachPB.protocolType = LAP_RARP;
  517.     lappb.csParam.TAttachPB.PHaddress = (ProcPtr) Lap802_readE_ph;
  518.     if (PBControl((ParmBlkPtr)&lappb, false) != noErr)
  519.         return;
  520.  
  521.         /* attach 802.3-RARP packet read handler to the LAP manager */
  522.     rc = L802Attach((ProcPtr) Lap802p3_ph, (long) lap->link_unit, prot_RARP);
  523.     if (rc != noErr)
  524.         /* can't open RARP IEEE 802.3 type */
  525.         return;
  526.  
  527.     rtxCount = 0;
  528.     rtxInterval = 60;
  529.  
  530.     SendRARP(lap, RARP_REQUEST);
  531.     rtxTime = TickCount() + rtxInterval;
  532.     while (lap->our_ip_addr == 0) {
  533.         if (TickCount() >= rtxTime) {
  534.             /* time to retransmit reverse ARP */
  535.             rtxCount++;
  536.             rtxInterval += rtxInterval;
  537.             if (rtxCount < MAX_ARP_COUNT) {
  538.                 SendRARP(lap, RARP_REQUEST);
  539.                 rtxTime = TickCount() + rtxInterval;
  540.             }
  541.             else
  542.                 break;
  543.         }
  544.     }
  545.  
  546.         /* release ethernet-RARP listner */
  547.     lappb.csParam.TDetachPB.protocolType = LAP_RARP;
  548.     PBControl((ParmBlkPtr)&lappb, false);
  549.  
  550.         /* release 802.3-RARP listener */
  551.     rc = L802Detach((long) lap->link_unit, prot_RARP);
  552. }
  553.  
  554. void SendRARP (lap,arp_code)
  555. struct Lap802Info *lap;
  556. int arp_code;
  557. {
  558.     struct ipbuf *ipb;
  559.     struct arp_header *arp_hdr;
  560.     struct Lap802_header *lap_hdr;
  561.     short oldPS;
  562.  
  563.     ipb = lap->arp_ipb;       
  564.     oldPS = Disable();
  565.     if (ipb->iop.ioResult <= 0) {
  566.         /* ipbuf available for sending RARPs */
  567.  
  568.         lap_hdr = (struct Lap802_header *)ipb->laphdr.ptr;
  569.             lap_hdr->lap_dest = lap->lap_broadcast_addr;
  570.         lap_hdr->lap_ls.lap_type = LAP_RARP;
  571.  
  572.            arp_hdr = (struct arp_header *)ipb->ip.ptr;
  573.             arp_hdr->arp_opcode = arp_code;
  574.             arp_hdr->arp_sha = lap->our_lap_addr;
  575.         arp_hdr->arp_spa = 0;
  576.         arp_hdr->arp_tha = lap->our_lap_addr;
  577.             arp_hdr->arp_tpa = 0;
  578.  
  579.         Lap802_writeit(lap, ipb);
  580.     }
  581.     Enable(oldPS);
  582. }
  583.  
  584. Boolean Lap802_probe(lap, addr)
  585. struct Lap802Info *lap;
  586. ip_addr addr;
  587. {
  588.     int ticks;
  589.  
  590.     SendARP(lap, ARP_REQUEST, addr, &lap->lap_broadcast_addr);
  591.  
  592.     /* wait around a few milliseconds to see if anyone responds */
  593.     ticks = TickCount() + 5;
  594.     while ((TickCount() <= ticks) && (lap->addressConflict == false))
  595.         /* wait around */
  596.         ;
  597.     return(!lap->addressConflict);
  598. }
  599.  
  600. Boolean Lap802_register(lap)
  601. struct Lap802Info *lap;
  602. {
  603.     /* verify that no-one else is using our address, best we can do on the
  604.        Ethernet */
  605.     lap->addressConflict = false;
  606.     return(Lap802_probe(lap, lap->our_ip_addr));
  607. }
  608.  
  609. /* Lap802_close is called to close the Ethernet driver */
  610.  
  611. OSErr Lap802_close(lap)
  612. struct Lap802Info *lap;
  613. {
  614.     OSErr    rc = -1;
  615.     struct Lap802PB lappb;
  616.     char prot_IP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_0,HEX_0};
  617.     char prot_ARP[] = {HEX_1,HEX_AA,HEX_5,HEX_0,HEX_0,HEX_0,HEX_8,HEX_6,HEX_0};
  618.     
  619.     /* kill any pending VRT tasks or ARP requests */
  620.     Arp_close(lap);
  621.  
  622.         /* release ethernet-IP listner */
  623.     bzero((char *)&lappb, sizeof(lappb));
  624.     lappb.ioRefNum = lap->link_unit;
  625.     lappb.csCode = TDetachPH;
  626.     lappb.csParam.TDetachPB.protocolType = LAP_IP;
  627.     PBControl((ParmBlkPtr)&lappb, false);
  628.  
  629.         /* release ethernet-ARP listner */
  630.     lappb.csParam.TDetachPB.protocolType = LAP_ARP;
  631.     PBControl((ParmBlkPtr)&lappb, false);
  632.  
  633.         /* release 802.3-IP listner */
  634.     rc = L802Detach((long) lap->link_unit, prot_IP);
  635.  
  636.         /* release 802.3-ARP listner */
  637.     rc = L802Detach((long) lap->link_unit, prot_ARP);
  638.  
  639.     return(noErr);
  640. }
  641.